#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

const int Maxn = 10010;
const double Eps = 1e-12;
struct point {
	double x, y;
	point() {}
	point( double _x, double _y ) : x( _x ), y( _y ) {}
	inline point operator + ( const point Other ) const {
		return point( x + Other.x, y + Other.y );
	}
	inline point operator - ( const point Other ) const {
		return point( x - Other.x, y - Other.y );
	}
	inline point operator * ( const double Other ) const {
		return point( x * Other, y * Other );
	}
	inline double operator * ( const point Other ) const {
		return x * Other.y - Other.x * y;
	}
	inline double operator / ( const point Other ) const {
		return x * Other.x + y * Other.y;
	}
	inline double Dis() const { return sqrt( x * x + y * y ); }
};
int N, M, L;
point A[ Maxn ], B[ Maxn ], C[ Maxn << 1 ], Base;

inline int Cmp( double x, double y ) {
	if( fabs( x - y ) <= Eps ) return 0;
	if( x - y > Eps ) return 1;
	return -1;
}
inline bool Cmp1( point x, point y ) {
	return Cmp( ( x - Base ) * ( y - Base ), 0.0 ) == 1 || 
		( Cmp( ( x - Base ) * ( y - Base ), 0.0 ) == 0 && Cmp( ( x - Base ).Dis(), ( y - Base ).Dis() ) == -1 );
}
void Get( point *A, int &N ) {
	for( int i = 2; i <= N; ++i )
		if( Cmp( A[ i ].y, A[ 1 ].y ) == -1 || ( Cmp( A[ i ].y, A[ 1 ].y ) == 0 && Cmp( A[ i ].x, A[ 1 ].x ) == -1 ) )
			swap( A[ i ], A[ 1 ] );
	Base = A[ 1 ]; sort( A + 2, A + N + 1, Cmp1 );
	L = 1; C[ 1 ] = A[ 1 ];
	for( int i = 2; i <= N; ++i ) {
		for( ; L > 1 && Cmp( ( A[ i ] - C[ L - 1 ] ) * ( C[ L ] - C[ L - 1 ] ), 0.0 ) >= 0; --L );
		C[ ++L ] = A[ i ];
	}
	N = L; for( int i = 1; i <= L; ++i ) A[ i ] = C[ i ];
	return;
}
void Merge( point *A, int N, point *B, int M, point *C ) {
	L = 1; C[ 1 ] = A[ 1 ] + B[ 1 ];
	A[ ++N ] = A[ 1 ]; B[ ++M ] = B[ 1 ];
	int i1 = 1, i2 = 1;
	for( ; i1 < N && i2 < M; ) {
		if( Cmp( ( A[ i1 + 1 ] - A[ i1 ] ) * ( B[ i2 + 1 ] - B[ i2 ] ), 0.0 ) >= 0 ) {
			C[ L + 1 ] = C[ L ] + ( A[ i1 + 1 ] - A[ i1 ] ); ++L; ++i1;
		} else {
			C[ L + 1 ] = C[ L ] + ( B[ i2 + 1 ] - B[ i2 ] ); ++L; ++i2;
		}
	}
	for( ; i1 < N; ++i1 ) C[ L + 1 ] = C[ L ] + ( A[ i1 + 1 ] - A[ i1 ] ), ++L;
	for( ; i2 < M; ++i2 ) C[ L + 1 ] = C[ L ] + ( B[ i2 + 1 ] - B[ i2 ] ), ++L;
	return;
}
bool Check() {
	for( int i = 1; i < L; ++i )
		if( Cmp( C[ i + 1 ] * C[ i ], 0.0 ) > 0 ) return false;
	return true;
}
double GetDis( point A, point B, point C ) {
	point D = C + point( -( A - B ).y, ( A - B ).x );
	double T = ( D - A ) * ( C - A ) / ( ( C - B ) * ( D - B ) );
	if( Cmp( T, 0.0 ) <= 0 ) return min( A.Dis(), B.Dis() );
	point O = A * ( 1 / ( T + 1.0 ) ) + B * ( T / ( T + 1.0 ) );
	return ( O - C ).Dis();
}
int main() {
	scanf( "%d%d", &N, &M );
	while( N != 0 || M != 0 ) {
		for( int i = 1; i <= N; ++i ) scanf( "%lf%lf", &A[ i ].x, &A[ i ].y );
		for( int i = 1; i <= M; ++i ) scanf( "%lf%lf", &B[ i ].x, &B[ i ].y );
		for( int i = 1; i <= M; ++i ) B[ i ].x = -B[ i ].x, B[ i ].y = -B[ i ].y;
		Get( A, N ); Get( B, M );
		Merge( A, N, B, M, C );
		if( Check() ) printf( "0.000000\n" );
		else {
			double Ans = 1000000000.0;
			for( int i = 1; i < L; ++i ) Ans = min( Ans, GetDis( C[ i ], C[ i + 1 ], point( 0.0, 0.0 ) ) );
			printf( "%.6lf\n", Ans );
		}
		scanf( "%d%d", &N, &M );
	}
	return 0;
}
